package com.ruoyi.asset.utils;

import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

public class RSAUtils {

    // 用户提供的公钥字符串
    public static final String PUBLIC_KEY = 
        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUGcnSVq8E8cVr5QlapXi2OZrj+5sr63X+judi96NpJP0ge7Hcs3uYOghyV3JkIapM3o2AKVhe7eHPNNccvuQRIz7jVzNiyqNeCkVYc5teORjjCAx8Fb2+dtb45szBDAH9WBlI/VtCt5lF/zUgx3WvSkieThn/83mjCOQ8tLwH1QIDAQAB";

    // 用户提供的私钥字符串
    public static final String PRIVATE_KEY = 
        "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJUpUIetqLeIFMGfSHbstE5ZEsk5FIp1Eenh2wIwItkbz/adhAvo6/Ah2D7XIQ5TgvmicPgMfERDPCmEbrEhJSGYcw98J2v9fHV5wgZvuR2Jp3pQki7zHfVmXnL+HrSaTvJPuHmNRJCInQxSUk7y9HqtTTFIjKkuSklOetfqwo9JAgMBAAECgYAU4dbTV92R7Cwzuy/y7kqD2XaG00Xr6F3cp3D4ynJmgL1Jol21KSO215YlngqTrd9dQX+dSmovSFZo3ZB9nc1LwWZZHS6rw1bukoe4jNTbhpTaC6zPtIlRE3ppxG7ji9tAACJYY7kADfll2CCa8eRPZ6+2SE8BszHYb7koQo8HzQJBAPmaWLVBSgFNomo66EatHt+QffYbErs3w/iVorfZmREFFvEfAenFE74yoQku9Jj5BgSPkDAlDQL2Fo/1g+SjogcCQQCY+/e3wRSeqgqvJXye68k4Urvw6pXqsaojYmD6YuhJnz2hG6SdWUSf9tq9ObNJ9Z2sz6efsWkMHo2a2HnzVbAvAkEA3Xvyf1QiASoMlssS1bRFEwi6XSoE4xBG20yciRuTUaD8jJWBMxjnvfxbHTUHYr6GcoGZ5r7Z3ujTeIbZtIbm/QJAOIe7BMqzLOIWqpvGjg8AvvBLhH2awiu+e+7JeRx9S18tbdACJyaqZhXYxF2C88xv5ECjZy4ubA0KNHLTtWgvfwJAJsnXV/rAsMJrmD11Ge2xD2wGaYgpyo1EZXUqVKSuwVYHQI7c/NiKAGDmtdIJ+htfFhkGC72LDddtZPA6/04juA==";

    // RSA最大加密明文大小
    private static final int MAX_ENCRYPT_BLOCK = 117;

    // RSA最大解密密文大小
    private static final int MAX_DECRYPT_BLOCK = 128;


    /**
     * 使用公钥加密数据
     * @param data 待加密的数据
     * @param publicKey 公钥字符串
     * @return 加密后的Base64编码字符串
     * @throws Exception 加密过程中的异常
     */
    public static String encrypt(String data, String publicKey) throws Exception {
        // 解码公钥
        byte[] keyBytes = Base64Utils.decodeFromString(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
//        PublicKey pubKey = generatePublicKeyFromPrivateKey(PRIVATE_KEY);
        // 加密数据
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64Utils.encodeToString(encryptedBytes);
    }

//    /**
//     * 使用私钥解密数据
//     * @param encryptedData 加密的Base64编码字符串
//     * @param privateKey 私钥字符串
//     * @return 解密后的原始数据
//     * @throws Exception 解密过程中的异常
//     */
//    public static String decrypt(String encryptedData, String privateKey) throws Exception {
//        // 解码私钥
//        byte[] keyBytes = Base64Utils.decodeFromString(privateKey);
//        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        PrivateKey privKey = keyFactory.generatePrivate(keySpec);
//
//        // 解密数据
//        Cipher cipher = Cipher.getInstance("RSA");
//        cipher.init(Cipher.DECRYPT_MODE, privKey);
//        byte[] decryptedBytes = cipher.doFinal(Base64Utils.decodeFromString(encryptedData));
//        return new String(decryptedBytes, StandardCharsets.UTF_8);
//    }

    // 分段解密
    public static String decryptByPrivateKey(String encryptedDataBase64, String privateKeyBase64) throws Exception {
        // 加载私钥
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 初始化Cipher
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 计算分段大小（1024位密钥对应128字节）
        int maxBlockSize = 128;
        byte[] encryptedData = Base64.getDecoder().decode(encryptedDataBase64);

        // 分段解密
        List<Byte> decryptedBytes = new ArrayList<>();
        for (int i = 0; i < encryptedData.length; i += maxBlockSize) {
            int length = Math.min(maxBlockSize, encryptedData.length - i);
            byte[] decryptedBlock = cipher.doFinal(encryptedData, i, length);

            for (byte b : decryptedBlock) {
                decryptedBytes.add(b);
            }
        }

        // 转换为字符串
        byte[] result = new byte[decryptedBytes.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = decryptedBytes.get(i);
        }
        return new String(result, StandardCharsets.UTF_8);
    }

    private static byte[] decrypt(byte[] data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 返回UTF-8编码的解密信息
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        String s = new String(decryptedData, "UTF-8");
        System.out.println(s);
        return null;
    }



//    public static String decrypt(String str, String privateKey) throws Exception {
//        // 获取公钥
//        byte[] decoded = Base64Utils.decodeFromString(privateKey);
//        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
//                .generatePrivate(new PKCS8EncodedKeySpec(decoded));
//        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//        cipher.init(2, priKey);
//        byte[] data = Base64Utils.decodeFromString(String.valueOf(str.getBytes("UTF-8")));
//
//        // 返回UTF-8编码的解密信息
//        int inputLen = data.length;
//        ByteArrayOutputStream out = new ByteArrayOutputStream();
//        int offSet = 0;
//        byte[] cache;
//        int i = 0;
//        // 对数据分段解密
//        while (inputLen - offSet > 0) {
//            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
//                cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
//            } else {
//                cache = cipher.doFinal(data, offSet, inputLen - offSet);
//            }
//            out.write(cache, 0, cache.length);
//            i++;
//            offSet = i * 128;
//        }
//        byte[] decryptedData = out.toByteArray();
//        out.close();
//        return URLDecoder.decode(new String(decryptedData, "UTF-8"), "UTF-8");
//    }


    /**
     * 使用默认公钥加密
     */
    public static String encrypt(String data) throws Exception {
        return encryptByPublicKey(data, PUBLIC_KEY);
    }

    // 分段加密
    public static String encryptByPublicKey(String plaintext, String publicKeyBase64) throws Exception {
        // 加载公钥
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        // 初始化Cipher
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 计算分段大小（1024位密钥对应117字节）
        int maxBlockSize = 117;
        byte[] plaintextBytes = plaintext.getBytes(StandardCharsets.UTF_8);

        // 分段加密
        List<Byte> encryptedBytes = new ArrayList<>();
        for (int i = 0; i < plaintextBytes.length; i += maxBlockSize) {
            int length = Math.min(maxBlockSize, plaintextBytes.length - i);
            byte[] encryptedBlock = cipher.doFinal(plaintextBytes, i, length);

            for (byte b : encryptedBlock) {
                encryptedBytes.add(b);
            }
        }

        // 转换为Base64字符串
        byte[] result = new byte[encryptedBytes.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = encryptedBytes.get(i);
        }
        return Base64.getEncoder().encodeToString(result);
    }

    /**
     * 使用默认私钥解密
     */
    public static String decrypt(String encryptedData) throws Exception {
        byte[] keyBytes = Base64Utils.decodeFromString(PRIVATE_KEY);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privKey = keyFactory.generatePrivate(keySpec);
//        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec();
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        PrivateKey privKey = keyFactory.generatePrivate(keySpec);
//        byte[] decrypt = decrypt(Base64Utils.decodeFromString(encryptedData), privKey);
        String s = decryptByPrivateKey(encryptedData, PRIVATE_KEY);
        return s;
//        return new String(decrypt, StandardCharsets.UTF_8);

    }

    // 测试示例
    public static void main(String[] args) {
        try {
            String originalData = "Hello, RSA encryption!";
            System.out.println("原始数据: " + originalData);

            // 加密
            String encryptedData = encrypt(originalData);
            System.out.println("加密后: " + encryptedData);

            // 解密
            String decryptedData = decrypt(encryptedData);
            System.out.println("解密后: " + decryptedData);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static PublicKey generatePublicKeyFromPrivateKey(String privateKeyBase64) throws Exception {
        // 解码私钥字符串
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);

        // 生成PrivateKey对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 从私钥提取公钥
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
        java.security.spec.RSAPublicKeySpec publicKeySpec =
                new java.security.spec.RSAPublicKeySpec(rsaPrivateKey.getModulus(),
                        java.math.BigInteger.valueOf(65537));

        return keyFactory.generatePublic(publicKeySpec);
    }
}    